package com.lagou.rpc.common;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @param
 * @author oyz
 * @version 1.0
 * @description: TODO 请求耗时统计，单位:毫秒
 * @date 2022/2/27 20:18
 */
@NoArgsConstructor
@Data
public class RequestMetrics {

    /**
     节点-统计最后一次耗时(毫秒)
     */
    private static final ConcurrentHashMap<String,Long> COST_TIME_MAP = new ConcurrentHashMap<>();

    /**
     * 请求id--耗时对象(手段:存入顺序的节点，来判断耗时多长时间)
     */
    private static final ConcurrentHashMap<String,Metries> REQUEST_ID_MAP = new ConcurrentHashMap<>();
    /**
     * 防止里边的对象属性被多线程篡改
     */
    private static RequestMetrics requestMetrics;



    /**
     * @description: TODO 全局单例,防止多线程篡改
     * @author 10843
     * @param
     * @date 2022/2/27 20:38
     * @version 1.0
     */
    public static RequestMetrics getInstance(){
        if (requestMetrics == null){
            synchronized (RequestMetrics.class){
                requestMetrics = new RequestMetrics();
            }
        }
        return requestMetrics;
    }

    /**
     * @description: TODO 获取统计数据的map，目的是为了拿到里边的value对象
     * @author oyz
     * @param null
     * @date 2022/2/27 20:32
     * @version 1.0
     */
    public ConcurrentHashMap<String,Long> getMetriesMap(){
        return COST_TIME_MAP;
    }

    /**
     * @description: TODO 增加节点
     * @author oyz
     * @param ip
     * @param port
     * @date 2022/2/27 20:40
     * @version 1.0
     */
    public void addNode(String ip,int port){
        COST_TIME_MAP.put(ip+":"+port,0L);
    }


    /**
     * @description: TODO 删除节点
     * @author oyz
     * @param ip
     * @param port
     * @date 2022/2/27 20:44
     * @version 1.0
     */
    public void removeNode(String ip,int port){
        COST_TIME_MAP.remove(ip+":"+port);
    }
    /**
     * @description: TODO 在客户端接收到响应的时候，计算耗时
     * @author 10843
     * @param
     * @date 2022/2/27 20:52
     * @version 1.0
     */
    public void calulate(String requestId){
        Metries metries = REQUEST_ID_MAP.get(requestId);
        long cost = System.currentTimeMillis() - metries.start;
        // 放入统计计时的map
        COST_TIME_MAP.put(metries.getIp()+":"+metries.getPort(),cost);
        // 移除原来耗时对象的map
        REQUEST_ID_MAP.remove(requestId);
    }
    /**
     * @description: TODO 服务端注册是放入map保存信息
     * @author oyz
     * @param
     * @date 2022/2/27 21:16
     * @version 1.0
     */
    public void putProvider(String requestId,String ip,int port){
        REQUEST_ID_MAP.put(requestId,new Metries(ip,port,System.currentTimeMillis(),null));
    }


    /**
     * @description: TODO 获取所有节点的耗时信息
     * @author oyz
     * @param null
     * @date 2022/2/27 21:17
     * @version 1.0
     */
    public List<Metries> getAllInstances(){
        List<Metries> result = new ArrayList<>();
        COST_TIME_MAP.forEach((s,cost)->{
            String[] split = s.split(":");
            result.add(new Metries(split[0],Integer.parseInt(split[1]),cost));
        });
        return  result;
    }



    /**
     * @description: TODO 创建内部类，重写比较方法
     * @author oyz
     * @param null
     * @date 2022/2/27 20:26
     * @version 1.0
     */
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class  Metries implements Comparable<Metries>{
        private String ip;
        private int port;
        /**
         * 开始时间
         */
        private Long start;

        /**
         * 花费的时间
         */
        private Long cost;

        public Metries(String s, int s1, Long cost) {
            this.ip = s;
            this.port = s1;
            this.cost = cost;
        }


        @Override
        public int compareTo(Metries o) {
            return getCost().compareTo(o.getCost());
        }
    }
}
